package ops

import (
	"errors"
	"fcs-api/src/app/handler"
	"fcs-api/src/app/model"
	"fmt"
	"gopkg.in/yaml.v2"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"reflect"
)

const layerCmName = "layer-config"
const layerNs = "fcs"
const layerConfigKey = "layer-config"
const defaultLayerRootDir = "/layer"
const defaultHostDir = "/nfs-layer"

type layerConfig struct {
	OssEndPoint       string `yaml:"ossEndPoint"`
	LayerRootDir      string `yaml:"layerRootDir"`
	OssBucket         string `yaml:"ossBucket"`
	Ak                string `yaml:"ak"`
	Sk                string `yaml:"sk"`
	HostDir           string `yaml:"hostDir"`
	NfsServerEndpoint string `yaml:"nfsServerEndpoint"`
}

// InitLayerConfigMap 用于初始化函数计算集群中 layer-controller 组件的 configmap
func InitLayerConfigMap(api *handler.APIHandler) error {

	if handler.Ak == "" || handler.Sk == "" {
		_ = logger.Warn("InitLayerConfigMap: ak sk not init")
		return errors.New("ak sk not init error")
	}

	fcClient, err := handler.GetFcClient(api)
	if err != nil {
		_ = logger.Error("InitLayerConfigMap: get fcClient error %v", err)
		return err
	}

	cm, err := fcClient.GetConfigMap(layerNs, layerCmName)
	if err != nil {
		// 如果没有找到，那么说明没有安装 layer-controller，不需要进行初始化
		if apierrors.IsNotFound(err) {
			return nil
		}
		_ = logger.Error("InitLayerConfigMap: get layer cm error %v", err)
		return err
	}
	var config layerConfig
	configString, isExist := cm.Data[layerConfigKey]
	if !isExist {
		_ = logger.Warn("InitLayerConfigMap: layer-config data not found, init a new one")
	} else {
		err = yaml.Unmarshal([]byte(configString), &config)
		// 如果反序列化配置出错，不返回错误，重新生成一份新的配置更新上
		if err != nil {
			_ = logger.Error("InitLayerConfigMap: covert config to yaml error, %v", err)
		}
	}

	// 根据标签筛选出安装 nfs server 的节点
	labelSelector := fmt.Sprintf("%s=%s", model.NFSNodeLabelKey, "true")
	nodes, err := fcClient.GetNodes(labelSelector)
	if err != nil {
		_ = logger.Error("InitLayerConfigMap: get node list error %v", err)
		return err
	} else if len(nodes.Items) == 0 {
		_ = logger.Warn("InitLayerConfigMap: no match node %v", err)
		return errors.New("didn't find match node error")
	}
	var nfsAddress string
	for _, address := range nodes.Items[0].Status.Addresses {
		if address.Type == model.NodeIntIPStr {
			nfsAddress = address.Address
		}
	}

	config.LayerRootDir = defaultLayerRootDir
	config.HostDir = defaultHostDir
	// 深拷贝一份新的配置
	configNew := config
	configNew.Ak = handler.Ak
	configNew.Sk = handler.Sk
	configNew.OssEndPoint = model.Base.OssEndpoint
	configNew.OssBucket = model.Base.OssBucket
	configNew.NfsServerEndpoint = nfsAddress
	// 新老配置比较是否相同
	if !reflect.DeepEqual(config, configNew) {
		configNewStr, err := yaml.Marshal(&configNew)
		if err != nil {
			_ = logger.Error("InitLayerConfigMap: marshal config error, %v, config data is %s", err, string(configNewStr))
			return err
		}
		cm.Data[layerConfigKey] = string(configNewStr)
		_, err = fcClient.UpdateConfigMap(layerNs, cm)
		if err != nil {
			_ = logger.Error("InitLayerConfigMap: save config error %v", err)
			return err
		}
	}
	return nil
}
